/*
按位运算

小端法、掩码、按位与、或和非
*/
#include <stdio.h>

void ShowHexPerByte(unsigned char *point, size_t len);
void RemainLowValidBytes(unsigned int uiNum, size_t start, size_t end);
void OppositeHighValidBytes(unsigned int uiNum, size_t start, size_t end);
void OneLowValidBytes(unsigned int uiNum, size_t start, size_t end);

int main(int argc, const char *argv[])
{
    // 2271560481（十进制数）
    unsigned int uiNum = 0x87654321;
    printf("十六进制数字：0X%.8X\n", uiNum);

    // 21 43 65 87 小端法
    // 以字节为单位，打印对应字节上的十六进制数
    ShowHexPerByte((unsigned char *)&uiNum, sizeof(unsigned int));

    // 保留最低有效字节，其他位均设置为0
    RemainLowValidBytes(uiNum, 1, 4);

    // 保留最低有效字节，其他的位取补
    OppositeHighValidBytes(uiNum, 1, 4);

    // 最低有效字节设置成全1，其他字节都保持不变
    OneLowValidBytes(uiNum, 0, 1);

    return 0;
}

/* 以字节为单位，打印对应字节上的十六进制数 */
void ShowHexPerByte(unsigned char *point, size_t len)
{
    int i=0;

    printf("在内存中的排列：");
    // 以字节为单位，打印对应字节上的十六进制数
    for (;i<len;i++) {
        printf("%.2X ", *(point+i));
    }

    printf("\n");
}

/* 保留最低有效字节，其余位均设置为0 */
void RemainLowValidBytes(unsigned int uiNum, size_t start, size_t end)
{
    unsigned char *point = (unsigned char *)&uiNum;
    int iFlag = 0x0;

    // 第２种方法：掩码运算
    // uiNum & 0xFF
    for (;start<end;start++) {
        *(point+start) = *(point+start) & iFlag;
    }

    printf("保留最低有效字节，其他位均设置为0：");
    printf("0X%.8X\t", uiNum);
    printf("十进制：%u\n", uiNum); 
}

/* 保留最低有效字节，其余位取补 */
void OppositeHighValidBytes(unsigned int uiNum, size_t start, size_t end)
{
    unsigned char *point = (unsigned char *)&uiNum;

    // 第２种方法：uiNum ^ ~0xFF（更优写法）
    // 等价于uiNum ^ 0xFFFFFF00
    // ~0xFF创建8个最低位等于0，其余位为1的掩码
    // ~0xFF产生的掩码，与字长无关
    // OxFFFFFF00只能工作在32位的机器上
    for (; start<end; start++) {
        *(point+start) =  ~(*(point+start));
    }

    printf("保留最低有效字节，其他的位取补：");
    printf("0X%.8X\t", uiNum);
    printf("十进制：%u\n", uiNum);    
}

/* 最低有效字节设置成全1，其他字节都保持不变 */
void OneLowValidBytes(unsigned int uiNum, size_t start, size_t end)
{
    unsigned char *point = (unsigned char *)&uiNum;
    int iFlag = 0xFF;

    // 第２种方法：uiNum | 0xFF
    for (;start<end;start++) {
        *(point+start) |= iFlag;
    }

    printf("最低有效字节设置成全1，其他字节都保持不变：");
    printf("0X%.8X\t", uiNum);
    printf("十进制：%u\n", uiNum);        
}